`include "common_def.v"
module MODULE_REGS(
	input 							clk_i,
	input 							rst_i,
	//write regs;
		//input from exu
	input 	[`WIDTH-1:0]	data_dst_w_i,
	input		[`WIDTH-1:0]	npc_i,
	input									pc_jump_i,
		//input from idu
	input 	[4:0] 			addr_dst_w_i,
	input								wen_i,
	//read regs;
		//input from idu
	input 	[4:0]				addr_src1_r_i,
	input		[4:0]				addr_src2_r_i,
		//output to exu
	output 	[`WIDTH-1:0]	data_src1_r_o,
	output 	[`WIDTH-1:0]	data_src2_r_o,
	//pc out to ifu
	output 	[`WIDTH-1:0] pc_o,

	//0 to stop all regs write
	input 						npc_valid_i,
	input							pc_recover_i,
	input		[`WIDTH-1:0] pc_difftest_i,//delete
	// for forwarding unit
	input	 [`R_ADDR_W-1:0]	addr1_fw_i,
	output	[`WIDTH-1:0]			data1_fw_o,
	input	 [`R_ADDR_W-1:0]	addr2_fw_i,
	output	[`WIDTH-1:0]			data2_fw_o
);

//regs
wire 	[`WIDTH-1:0]		zeros;//zeros reg
wire  [`WIDTH-1:0]		out[33];//out of 32 regs


assign zeros[`WIDTH-1:0] = 0;
assign out[0] = zeros[`WIDTH-1:0];

//generate 31 regs 
genvar i;
generate
	for(i=1;i<32;i++) begin
Reg #(`WIDTH,0) r (clk_i,rst_i,data_dst_w_i[`WIDTH-1:0],out[i][`WIDTH-1:0],wen_i&(addr_dst_w_i == i));
	end
endgenerate

//use mux to choose data_src1_r from out according to the addr_src1_r;
MuxKey #(32,5,`WIDTH) mux_src1_r(data_src1_r_o[`WIDTH-1:0],addr_src1_r_i[4:0],{
	5'd0,	out[0][`WIDTH-1:0],				
	5'd1,	out[1][`WIDTH-1:0],				
	5'd2,	out[2][`WIDTH-1:0],				
	5'd3,	out[3][`WIDTH-1:0],				
	5'd4,	out[4][`WIDTH-1:0],				
	5'd5,	out[5][`WIDTH-1:0],				
	5'd6,	out[6][`WIDTH-1:0],				
	5'd7,	out[7][`WIDTH-1:0],				
	5'd8,	out[8][`WIDTH-1:0],				
	5'd9,	out[9][`WIDTH-1:0],				
	5'd10,	out[10][`WIDTH-1:0],				
	5'd11,	out[11][`WIDTH-1:0],				
	5'd12,	out[12][`WIDTH-1:0],				
	5'd13,	out[13][`WIDTH-1:0],				
	5'd14,	out[14][`WIDTH-1:0],				
	5'd15,	out[15][`WIDTH-1:0],				
	5'd16,	out[16][`WIDTH-1:0],				
	5'd17,	out[17][`WIDTH-1:0],				
	5'd18,	out[18][`WIDTH-1:0],				
	5'd19,	out[19][`WIDTH-1:0],				
	5'd20,	out[20][`WIDTH-1:0],				
	5'd21,	out[21][`WIDTH-1:0],				
	5'd22,	out[22][`WIDTH-1:0],				
	5'd23,	out[23][`WIDTH-1:0],				
	5'd24,	out[24][`WIDTH-1:0],				
	5'd25,	out[25][`WIDTH-1:0],				
	5'd26,	out[26][`WIDTH-1:0],				
	5'd27,	out[27][`WIDTH-1:0],				
	5'd28,	out[28][`WIDTH-1:0],				
	5'd29,	out[29][`WIDTH-1:0],				
	5'd30,	out[30][`WIDTH-1:0],				
	5'd31,	out[31][`WIDTH-1:0]				
});
//use mux to choose data_src2_r from out according to the addr_src2_r;
MuxKey #(32,5,`WIDTH) mux_src2_r(data_src2_r_o[`WIDTH-1:0],addr_src2_r_i[4:0],{
	5'd0,	out[0][`WIDTH-1:0],				
	5'd1,	out[1][`WIDTH-1:0],				
	5'd2,	out[2][`WIDTH-1:0],				
	5'd3,	out[3][`WIDTH-1:0],				
	5'd4,	out[4][`WIDTH-1:0],				
	5'd5,	out[5][`WIDTH-1:0],				
	5'd6,	out[6][`WIDTH-1:0],				
	5'd7,	out[7][`WIDTH-1:0],				
	5'd8,	out[8][`WIDTH-1:0],				
	5'd9,	out[9][`WIDTH-1:0],				
	5'd10,	out[10][`WIDTH-1:0],				
	5'd11,	out[11][`WIDTH-1:0],				
	5'd12,	out[12][`WIDTH-1:0],				
	5'd13,	out[13][`WIDTH-1:0],				
	5'd14,	out[14][`WIDTH-1:0],				
	5'd15,	out[15][`WIDTH-1:0],				
	5'd16,	out[16][`WIDTH-1:0],				
	5'd17,	out[17][`WIDTH-1:0],				
	5'd18,	out[18][`WIDTH-1:0],				
	5'd19,	out[19][`WIDTH-1:0],				
	5'd20,	out[20][`WIDTH-1:0],				
	5'd21,	out[21][`WIDTH-1:0],				
	5'd22,	out[22][`WIDTH-1:0],				
	5'd23,	out[23][`WIDTH-1:0],				
	5'd24,	out[24][`WIDTH-1:0],				
	5'd25,	out[25][`WIDTH-1:0],				
	5'd26,	out[26][`WIDTH-1:0],				
	5'd27,	out[27][`WIDTH-1:0],				
	5'd28,	out[28][`WIDTH-1:0],				
	5'd29,	out[29][`WIDTH-1:0],				
	5'd30,	out[30][`WIDTH-1:0],				
	5'd31,	out[31][`WIDTH-1:0]				
});

//pc_save
wire [`WIDTH-1:0] pc_save;
Reg #(`WIDTH,`RST_PC) pc_save_reg(clk_i,rst_i,pc_o,pc_save,npc_valid_i);
//pc
Reg #(`WIDTH,`RST_PC) pc_reg (clk_i,rst_i,pc_jump_i ? npc_i[`WIDTH-1:0]:(pc_recover_i ? pc_save:pc_o+4),pc_o[`WIDTH-1:0],npc_valid_i|pc_recover_i);

//use mux to choose data for forwarding unit
MuxKey #(32,5,`WIDTH) data1_fw_mux(data1_fw_o[`WIDTH-1:0],addr1_fw_i[4:0],{
	5'd0,	out[0][`WIDTH-1:0],				
	5'd1,	out[1][`WIDTH-1:0],				
	5'd2,	out[2][`WIDTH-1:0],				
	5'd3,	out[3][`WIDTH-1:0],				
	5'd4,	out[4][`WIDTH-1:0],				
	5'd5,	out[5][`WIDTH-1:0],				
	5'd6,	out[6][`WIDTH-1:0],				
	5'd7,	out[7][`WIDTH-1:0],				
	5'd8,	out[8][`WIDTH-1:0],				
	5'd9,	out[9][`WIDTH-1:0],				
	5'd10,	out[10][`WIDTH-1:0],				
	5'd11,	out[11][`WIDTH-1:0],				
	5'd12,	out[12][`WIDTH-1:0],				
	5'd13,	out[13][`WIDTH-1:0],				
	5'd14,	out[14][`WIDTH-1:0],				
	5'd15,	out[15][`WIDTH-1:0],				
	5'd16,	out[16][`WIDTH-1:0],				
	5'd17,	out[17][`WIDTH-1:0],				
	5'd18,	out[18][`WIDTH-1:0],				
	5'd19,	out[19][`WIDTH-1:0],				
	5'd20,	out[20][`WIDTH-1:0],				
	5'd21,	out[21][`WIDTH-1:0],				
	5'd22,	out[22][`WIDTH-1:0],				
	5'd23,	out[23][`WIDTH-1:0],				
	5'd24,	out[24][`WIDTH-1:0],				
	5'd25,	out[25][`WIDTH-1:0],				
	5'd26,	out[26][`WIDTH-1:0],				
	5'd27,	out[27][`WIDTH-1:0],				
	5'd28,	out[28][`WIDTH-1:0],				
	5'd29,	out[29][`WIDTH-1:0],				
	5'd30,	out[30][`WIDTH-1:0],				
	5'd31,	out[31][`WIDTH-1:0]				
});
//use mux to choose data for forwarding unit
MuxKey #(32,5,`WIDTH) data2_fw_mux(data2_fw_o[`WIDTH-1:0],addr2_fw_i[4:0],{
	5'd0,	out[0][`WIDTH-1:0],				
	5'd1,	out[1][`WIDTH-1:0],				
	5'd2,	out[2][`WIDTH-1:0],				
	5'd3,	out[3][`WIDTH-1:0],				
	5'd4,	out[4][`WIDTH-1:0],				
	5'd5,	out[5][`WIDTH-1:0],				
	5'd6,	out[6][`WIDTH-1:0],				
	5'd7,	out[7][`WIDTH-1:0],				
	5'd8,	out[8][`WIDTH-1:0],				
	5'd9,	out[9][`WIDTH-1:0],				
	5'd10,	out[10][`WIDTH-1:0],				
	5'd11,	out[11][`WIDTH-1:0],				
	5'd12,	out[12][`WIDTH-1:0],				
	5'd13,	out[13][`WIDTH-1:0],				
	5'd14,	out[14][`WIDTH-1:0],				
	5'd15,	out[15][`WIDTH-1:0],				
	5'd16,	out[16][`WIDTH-1:0],				
	5'd17,	out[17][`WIDTH-1:0],				
	5'd18,	out[18][`WIDTH-1:0],				
	5'd19,	out[19][`WIDTH-1:0],				
	5'd20,	out[20][`WIDTH-1:0],				
	5'd21,	out[21][`WIDTH-1:0],				
	5'd22,	out[22][`WIDTH-1:0],				
	5'd23,	out[23][`WIDTH-1:0],				
	5'd24,	out[24][`WIDTH-1:0],				
	5'd25,	out[25][`WIDTH-1:0],				
	5'd26,	out[26][`WIDTH-1:0],				
	5'd27,	out[27][`WIDTH-1:0],				
	5'd28,	out[28][`WIDTH-1:0],				
	5'd29,	out[29][`WIDTH-1:0],				
	5'd30,	out[30][`WIDTH-1:0],				
	5'd31,	out[31][`WIDTH-1:0]				
});

//DPI-C for simulation
assign out[32][`WIDTH-1:0] = (pc_difftest_i[`WIDTH-1:0]!=0)?pc_difftest_i[`WIDTH-1:0]:`RST_PC;//delete
import "DPI-C" function void set_gpr_ptr(input [`WIDTH-1:0] a[]);//delete
initial set_gpr_ptr(out);//delete

endmodule
